package com.example.contestsystem.Controller;

import com.example.contestsystem.Entity.*;
import com.example.contestsystem.R.R;
import com.example.contestsystem.Service.ContestService;
import com.example.contestsystem.Service.FileService;
import com.example.contestsystem.Service.SignUpContestService;
import com.example.contestsystem.Service.TeamService;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.data.domain.Page;
import org.springframework.data.repository.query.Param;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;

@Controller
@RequestMapping("/contest")
public class ContestController {
    final ContestService contestService;
    final SignUpContestService signUpContestService;
    final FileService fileService;
    final TeamService teamService;
    private static final String UPLOAD_DIR = "D:\\Reserved\\";

    @GetMapping
    public String contest(Model model, HttpServletRequest httpServletRequest){
        Page<Contest> contestPage = this.contestService.findAllByPageIndex(0, 20);
        int prePage = contestPage.previousOrFirstPageable().getPageNumber();
        int nextPage = contestPage.nextOrLastPageable().getPageNumber();
        model.addAttribute("contests", contestPage);
        model.addAttribute("prePage", prePage);
        model.addAttribute("nextPage", nextPage);

        Student student = (Student)httpServletRequest.getSession().getAttribute("loginStu");
        Teacher teacher = (Teacher)httpServletRequest.getSession().getAttribute("loginTeacher");
        if(student != null)
            return "stu/index_f";
        if(teacher != null)
            return "teacher/index_f";
        return "index_f";
    }

    public ContestController(ContestService contestService, SignUpContestService signUpContestService,
                             FileService fileService, TeamService teamService) {
        this.contestService = contestService;
        this.signUpContestService = signUpContestService;
        this.fileService = fileService;
        this.teamService = teamService;
    }

    /**
     * 此方法实现学生报名比赛
     */
    @GetMapping("/participate")
    @ResponseBody
    public R participate(@Param("contestId") String contestId, HttpServletRequest httpServletRequest) {
        Student loginStu = (Student) httpServletRequest.getSession().getAttribute("loginStu");
        if (loginStu != null) {
            SignUpContest signUpContest = new SignUpContest();
            signUpContest.setContestId(contestId);
            signUpContest.setStuAccount(loginStu.getStuAccount());
            if (this.signUpContestService.participate(signUpContest) != null) {
                return R.ok(200, "SUCCESS");
            }
        }
        return R.error(-1, "FAIL");
    }


    /**
     * 此方法实现学生取消参加比赛
     */
    @GetMapping("/cancel")
    @ResponseBody
    public R cancel(@Param("contestId") String contestId, HttpServletRequest httpServletRequest) {
        Student loginStu = (Student) httpServletRequest.getSession().getAttribute("loginStu");
        if(loginStu == null){
            return R.error("当前用户未登录");
        }
        if (this.signUpContestService.cancel(contestId, loginStu.getStuAccount())) {
            return R.ok(200,"成功");
        } else {
            return R.error("数据库删除失败");
        }
    }

    /**
     * 此方法实现教师发布竞赛
     */
    @PostMapping("/publish")
    public String publish(@ModelAttribute Contest contest, HttpServletRequest httpServletRequest) {
        Teacher loginTeacher = (Teacher) httpServletRequest.getSession().getAttribute("loginTeacher");
        if (loginTeacher != null) {
            contest.setTeacherAccount(loginTeacher.getTeacherAccount());
            String contestId = this.contestService.createContest(contest);
            return "redirect:/contest/detail?contestId="+contestId;
        }
        return null;
    }

    /**
     * @param file 上传的文件
     */
    @PostMapping("/upload")
    @ResponseBody
    public R handleFileUpload(@RequestParam("contestId") String contestId,
                              @RequestParam("file") MultipartFile file,
                              HttpServletRequest httpServletRequest) {
        if (file.isEmpty()) {
            return R.error();
        }
        Teacher loginTeacher = (Teacher) httpServletRequest.getSession().getAttribute("loginTeacher");
        if(loginTeacher!=null && this.contestService.isPublisher(contestId, loginTeacher.getTeacherAccount())){
            if(this.contestService.uploadFile(file, contestId))
                return R.ok(200, "success");
        }
        return R.error();
    }

    /**
     * 此方法实现查看竞赛详情（竞赛信息，竞赛的文件）
     */
    @GetMapping("/detail")
    public String detail(@Param("contestId") String contestId, HttpServletRequest httpServletRequest,
                         Model model) {
        Contest contest = this.contestService.findByContestId(contestId);
        List<FileEntity> fileEntities = this.contestService.findFilesByContestId(contestId);
        Page<Team> teams = this.teamService.findByContestId(contestId, 0, 20);
        int prePage = teams.previousOrFirstPageable().getPageNumber();
        int nextPage = teams.nextOrLastPageable().getPageNumber();
        model.addAttribute("teams", teams);
        model.addAttribute("prePage", prePage);
        model.addAttribute("nextPage", nextPage);

        model.addAttribute("files", fileEntities);
        model.addAttribute("contest", contest);
        model.addAttribute("teams", teams);


        // 如果有学生登录了，且登录学生参加了该比赛，显示该小组信息和成员列表
        Student loginStu = (Student) httpServletRequest.getSession().getAttribute("loginStu");
        if(loginStu != null){
            this.teamService.findByStuAccountAndContestId(loginStu.getStuAccount(), contestId);
            return "stu/detail";
        }

        // 如果有老师登录了，且该比赛由登录老师发布，则显示小组列表
        Teacher loginTeacher = (Teacher) httpServletRequest.getSession().getAttribute("loginTeacher");
        if( loginTeacher != null ){
            return "teacher/contest_detail";
        }
        return "detail";
    }

    /**
     * 此方法实现下载文件
     * @param fileName 文件名
     */
    @GetMapping("/download")
    public ResponseEntity<byte[]> downloadFile(@Param("contestId") String contestId, @Param("fileName") String fileName) throws IOException {
        String filePath = UPLOAD_DIR + contestId + File.separator + fileName;
        File file = new File(filePath);

        // 包装了文件的二进制数据，并设置了Content-Disposition响应头，告诉浏览器将文件作为附件下载
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", fileName);

        return new ResponseEntity<>(Files.readAllBytes(file.toPath()), headers, HttpStatus.OK);
    }

    /**
     * 此方法实现老师删除自己发布的竞赛
     */
    @GetMapping("/delete")
    @ResponseBody
    public R deleteContest(@Param("contestId") String contestId, HttpServletRequest httpServletRequest){
        Teacher loginTeacher = (Teacher)httpServletRequest.getSession().getAttribute("loginTeacher");
        if(loginTeacher != null && this.contestService.isPublisher(contestId, loginTeacher.getTeacherAccount())){
            this.contestService.deleteContest(contestId, loginTeacher.getTeacherAccount());
            return R.ok(200,"成功");
        }
        return R.error(-1, "FAIL");
    }

    /**
     * 此方法实现老师删除自己上传的文件
     */
    @GetMapping("/deleteFile")
    @ResponseBody
    public R deleteFile(@Param("fileName") String fileName, @Param("contestId") String contestId,
                        HttpServletRequest httpServletRequest){
        Teacher loginTeacher = (Teacher)httpServletRequest.getSession().getAttribute("loginTeacher");
        if(loginTeacher!= null && this.contestService.isPublisher(contestId, loginTeacher.getTeacherAccount())){
            this.contestService.deleteFile(contestId, fileName);
            return R.ok();
        }
        return R.error();
    }

    @GetMapping("/isParticipated")
    @ResponseBody
    public R isParticipated(@Param("contestId") String contestId, HttpServletRequest httpServletRequest){
        Student loginStu = (Student)httpServletRequest.getSession().getAttribute("loginStu");
        if(loginStu!=null && this.contestService.checkParticipated(contestId, loginStu.getStuAccount())){
            return R.ok(200, "已报名");
        }
        return R.error(-1, "未报名");
    }

    @GetMapping("/isPublisher")
    @ResponseBody
    public R isPublisher(@Param("contestId") String contestId, HttpServletRequest httpServletRequest){
        Teacher loginTeacher = (Teacher)httpServletRequest.getSession().getAttribute("loginTeacher");
        if(this.contestService.isPublisher(contestId, loginTeacher.getTeacherAccount()))
            return R.ok(200, "yes");
        return R.error(-1, "no");
    }

}
